import {
  cadAppLog,
  CENTEREVENTS,
  CMEVENTS,
  CurveStyle,
  EventsRes,
  ICurve,
  MouseStyle,
  STATE,
  TrackBallControlState,
} from '@amcax/base';
import { userEvents } from '@app-cad/module';
import { Picker2D, Picker3D, PickerMgr } from '@amcax/renderer';
import { CIRCLE_BAR_EVENTS, KEYBOARD_KEY } from '@app-cad/common/Constants';
import { BaseEventCenter } from '@app-cad/common/events/BaseEventCenter';
import { cmdDrag, CmdDrag } from '../commands/sketch/cmd-drag';
import { DimDrag, dimDrag } from '../commands/sketch/cmd-render-pick/dimDrag';
import { dimPicker } from '../commands/sketch/cmd-render-pick/dimPick';
import { dimRender } from '../commands/sketch/cmd-render-pick/render';
import {
  addDimension,
  axis,
  CONSTRUCTION_LINE,
  deleteSketchCruve,
  hiddenPoint,
} from '@app-cad/common/utils';
import { constraintIconPicker } from '@app-cad/common/utils/sketchTools/ConstraintIconPicker';
import { ToolbarMouseControlManager } from '@app-base/common/commands/cmd-toolbar-mouse-control';
// 事件定义
export const SKETCH_CENTEREVENTS = {
  ...CENTEREVENTS,
  MOUSEDOWNMOVE: 'mousedownmove',
  PICK_SELECTED_INFO: 'pick_selected_info',
};
export const USER_EVENTS = {
  CIRCLEPOSITION: 'cicleposition',
  ARCPOSITION: 'arcposition',
  POINTPOSITION: 'pointposition',
};
type SketchInfo = {
  sketchId: string;
  frame: number[][];
};

/* 事件模块 */
export class SketchEventCenter extends BaseEventCenter {
  id = 'sketch';
  private selectedModels: ICurve[] = [];
  private picker: Picker2D = PickerMgr.getPicker<Picker2D>('2d');
  private sketchInfo: SketchInfo = null;
  private lineType: CurveStyle = 0; // 0 实线 1 虚线
  dimIsMove = false;
  clickTimerCount = 0;
  clickTimer: NodeJS.Timeout;

  setSketchInfo(info: SketchInfo) {
    this.sketchInfo = info;
  }

  getSelectedModels() {
    return this.selectedModels;
  }

  clearSelectedModels() {
    this.selectedModels = [];
  }

  getSketchInfo(): SketchInfo {
    return this.sketchInfo;
  }

  getLineType(): CurveStyle {
    return this.lineType;
  }

  setLineType(type: CurveStyle) {
    this.lineType = type;
  }

  // 暂时关闭事件中心
  sleep() {
    // 线拖拽关闭
    CmdDrag.removeInstance();
    // 尺寸拖拽关闭
    DimDrag.removeInstance();
    super.sleep();
  }

  // 鼠标双击
  onCanvasDbClick({ button, event }: EventsRes<PointerEvent>): void {
    if (this.state === STATE.DEFAULT && (button.onLeft || button.onRight)) {
      cadAppLog('选中模型');
      const pickerSelected = this.picker.select(event, this.mouse);
      if (pickerSelected) {
        this.emit(SKETCH_CENTEREVENTS.PICK_SELECTED_INFO, pickerSelected);
      }
    }
  }

  onCanvasPointerDown(ev: EventsRes<PointerEvent>): void {
    if (this.state === STATE.DEFAULT) {
      cmdDrag().onMouseDown(ev);
      this.picker.setPointerDownPos(ev);
      dimPicker().setPointerDownPos(ev);
    } else {
      dimRender().unPreview();
    }
  }

  onCanvasClick(ev: EventsRes<PointerEvent>): void {
    const { button } = ev;
    if (this.state === STATE.DEFAULT && button.onLeft && this.dimIsMove) {
      this.dimDragMouseUp();
    }
  }

  onCanvasPointerup(ev: EventsRes<PointerEvent>): void {
    const { event, button } = ev;
    // 鼠标抬起
    const rect = this.canvas.getBoundingClientRect();
    this.mouse = {
      x: Math.round(event.clientX - rect.left),
      y: Math.round(event.clientY - rect.top),
    };
    if (button.onRight) {
      this.clickTimerCount = this.clickTimerCount + 1;

      if (this.clickTimerCount === 1) {
        this.clickTimer = setTimeout(() => {
          this.clickTimerCount = 0;
        }, 300);
      } else {
        // 清除单击事件的定时器
        clearTimeout(this.clickTimer);
        this.clickTimerCount = 0;

        userEvents.emit(CIRCLE_BAR_EVENTS.CIRCLE_BAR_SHOW, ev);
      }

      // 鼠标右键删除，事件触发
      userEvents.emit(CMEVENTS.MODEL_RIGHT_CLICK, event);
    }
    if (this.state !== STATE.DEFAULT) {
      return;
    }
    cmdDrag().onMouseUp(ev);
    // 默认状态下支持多选和单击空白处清空
    // 鼠标左键和右键都可以选中模型
    if (button.onLeft || button.onRight) {
      cadAppLog('选中模型');
      constraintIconPicker.select(ev);
      this.picker.select(event, this.mouse);
      const select = !this.dimIsMove && dimPicker()?.select(event); // 框选功能
      const selectedModels =
        PickerMgr.getPicker<Picker2D>('2d').getSelectedObjectInfo(); // 获取选中的模型
      this.selectedModels = selectedModels;
      userEvents.emit(CONSTRUCTION_LINE, { type: 'isSelect' });
      if (selectedModels.length <= 2) {
        const curvedIds: string[] = [];
        let relative = null;
        selectedModels.forEach((item) => {
          if (
            item.type !== 'Bspline' &&
            !axis?.includes(item.id) &&
            !relative?.includes(item.id) &&
            !item?.relative?.includes(curvedIds[0])
          ) {
            curvedIds.push(item.id);
            relative = item.relative;
          }
        });
        dimRender().preview(curvedIds, (item) => {
          if (!item.disabled) {
            addDimension(this.sketchInfo.sketchId, item);
          }
        });
      } else {
        dimRender().unPreview();
      }
      if (!(select && select.length > 0)) {
        this.dimDragMouseUp();
      }
    }

    if (button.onLeft) {
      // 3d拾取清空（2d模式下设计树选中的原点和XYZ平面需清除）
      PickerMgr.getPicker<Picker3D>('3d').clickNull();
    }
  }

  dimDragMouseUp() {
    if (dimDrag().pickeDim) {
      dimDrag()?.onMouseUp();
      this.dimIsMove = false;
    }
  }

  // 恢复默认
  setDefault() {
    if (this.state === STATE.SLEEPING) {
      return this;
    }
    this.state = STATE.DEFAULT;
    this.clearExit();
    return this;
  }

  // 修改state
  setState(state: string) {
    dimRender().unPreview();
    this.state = state;
    this.touchExit();
    return this;
  }

  /**
   *
   * pointermove 事件
   */
  onCanvasPointerMove(ev: EventsRes<PointerEvent>): void {
    const { button } = ev;
    this.dimIsMove = false;
    if (this.state !== STATE.DEFAULT) {
      return;
    }
    const pickedConstraint = constraintIconPicker.pick(ev);
    if (!pickedConstraint) {
      cmdDrag().onMouseMove(ev);
      // 草图拾取
      if (!cmdDrag().selectedCurve) {
        const pick = this.picker.pick(ev, null, null, Array.from(hiddenPoint));
        let dimPick = null;
        if (!button.buttonDown) {
          if (ToolbarMouseControlManager.state === TrackBallControlState.NONE) {
            MouseStyle.setName('');
          }
          cmdDrag()?.setPickedCurve(pick);
          if (!pick) {
            dimPick = dimPicker()?.pick(ev);
            dimDrag()?.setPickeDim(dimPick, ev.mouse);
          } else {
            dimPicker().unHover();
            dimDrag()?.setPickeDim(null);
          }
        } else {
          if (button.onLeft) {
            dimDrag()?.onMouseMove(ev);
            this.dimIsMove = true;
          }
          this.picker.clearHover();
        }
      } else {
        dimRender().unPreview();
      }
      // 框选功能
      if (
        button.onLeft &&
        !cmdDrag().pickedCurve &&
        !dimDrag().pickeDim &&
        ToolbarMouseControlManager.state === TrackBallControlState.NONE
      ) {
        this.picker.marqueeSelection(ev);
        dimPicker().marqueeSelection(ev);
      }
    } else {
      this.picker.clearHover();
    }
  }

  /**
   *
   * offCavasEvent
   */
  offCanvasPointerUp(event: PointerEvent) {
    if (document.activeElement.tagName !== 'INPUT') {
      event.preventDefault();
    }
    event.stopPropagation();
    // 结束框选
    this.picker.marqueePointerUp();
    dimPicker().marqueePointerUp();
    return;
  }

  /**
   *
   * 键盘事件
   */

  onKeyUp({ event }: EventsRes<KeyboardEvent>): void {
    if (event.key === KEYBOARD_KEY.DELETE) {
      if (this.state === STATE.DEFAULT) {
        deleteSketchCruve();
      }
    }

    // 快捷撤销
    if (
      (event.key === KEYBOARD_KEY.KEY_Z ||
        event.key === KEYBOARD_KEY.KEY_UPPERCASE_Z) &&
      event.ctrlKey === true
    ) {
      userEvents.emit(CMEVENTS.CMD_SKETCH_UNDO, event);
    }

    // 快捷重做
    if (
      (event.key === KEYBOARD_KEY.KEY_Y ||
        event.key === KEYBOARD_KEY.KEY_UPPERCASE_Y) &&
      event.ctrlKey === true
    ) {
      userEvents.emit(CMEVENTS.CMD_SKETCH_REDO, event);
    }
  }
}

let eventCenter: SketchEventCenter;

export const sketchEventCenter = () => {
  if (eventCenter == null) {
    eventCenter = new SketchEventCenter();
  }
  return eventCenter;
};
